package com.sanley.coronavirus.common.security;

import com.sanley.coronavirus.common.utils.AesUtil;
import com.sanley.coronavirus.common.utils.JwtUtils;
import com.sanley.coronavirus.service.UserService;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.lang.Nullable;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 * @Author: ming
 * @create: 2022-10-14 21:19
 * @program: coronavirus
 */
@Slf4j
public class JWTAuthenticationFilter extends BasicAuthenticationFilter {
    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private UserService userService;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    String[] permitUrl;

    private final AntPathMatcher antPathMatcher = new AntPathMatcher();

    public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        for (String url : permitUrl) {
            if (antPathMatcher.match("/api"+url, request.getRequestURI())) {
                if (request.getRequestURI().equals("/api/login")) {
                    //直接解密
                    chain.doFilter(new FormContentRequestWrapper(request), response);
                    return;
                }
                chain.doFilter(request, response);
                return;
            }
        }

        String jwt = request.getHeader("Authorization");
        if (StringUtils.isEmpty(jwt)) {
            throw new JwtException("token异常！");
        }
        Claims claim = jwtUtils.parseToken(jwt);
        if (claim == null) {
            throw new JwtException("token异常！");
        }
        String username = claim.get("Username", String.class);

        if (!jwtUtils.validateToken(jwt)) {
            jwtUtils.removeTokenFromCache(username);
            throw new JwtException("token已过期");
        }

        List<SimpleGrantedAuthority> authorities = userService.getAuthorityByUsername(username);

        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken
                = new UsernamePasswordAuthenticationToken(username, null, authorities);
        SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
        chain.doFilter(request, response);
    }


    private static class FormContentRequestWrapper extends HttpServletRequestWrapper {

        public FormContentRequestWrapper(HttpServletRequest request) {
            super(request);
        }

        @Override
        @Nullable
        public String getParameter(String name) {
            String queryStringValue = super.getParameter(name);

            if (UsernamePasswordAuthenticationFilter.SPRING_SECURITY_FORM_PASSWORD_KEY.equals(name)) {
                // 解密操作
                queryStringValue = AesUtil.decrypt(queryStringValue);
            }

            return queryStringValue;
        }

    }

}
